import { Injectable, UnauthorizedException } from '@nestjs/common';
import {
  BusinessException,
  ParameterException,
} from '../../common/exceptions/bad-request.exception';
import { JwtService } from '@nestjs/jwt';
import { UserService } from './user.service';
import { JwtAuthService, JwtPayload } from '../../common/services/jwt.service';
import { LoginDto, RefreshTokenDto } from './dto/login.dto';
import { RegisterDto } from './dto/register.dto';
import { CaptchaUtil } from '../../common/utils/captcha.util';
import { PasswordUtil } from '../../common/utils/password.util';

@Injectable()
export class AuthService {
  constructor(
    private userService: UserService,
    private jwtService: JwtService,
    public jwtAuthService: JwtAuthService,
  ) {}

  /**
   * 用户注册
   */
  async register(registerDto: RegisterDto) {
    // 创建用户
    const user = await this.userService.create(registerDto);

    // 生成JWT令牌
    const tokens = this.jwtAuthService.generateTokenPair({
      id: user.id,
      username: user.username,
    });

    // 更新最后登录时间
    await this.userService.updateLastLoginTime(user.id);

    return {
      user: this.sanitizeUser(user),
      tokens,
    };
  }

  /**
   * 用户登录
   */
  async login(loginDto: LoginDto) {
    const { username, password } = loginDto;

    // 验证参数
    if (!username || !password) {
      throw new ParameterException(
        '用户名和密码不能为空',
        !username ? 'username' : 'password',
      );
    }

    // 查找用户
    const user = await this.userService.findByUsername(username);
    if (!user) {
      throw new BusinessException('用户名或密码错误', 'INVALID_CREDENTIALS');
    }

    // 验证密码
    const isPasswordValid = await PasswordUtil.verify(
      password,
      user.passwordHash,
    );
    if (!isPasswordValid) {
      throw new BusinessException('用户名或密码错误', 'INVALID_CREDENTIALS');
    }

    // 生成JWT令牌
    const tokens = this.jwtAuthService.generateTokenPair({
      id: user.id,
      username: user.username,
    });

    // 更新最后登录时间
    await this.userService.updateLastLoginTime(user.id);

    return {
      user: this.sanitizeUser(user),
      tokens,
    };
  }

  /**
   * 刷新令牌
   */
  async refreshToken(refreshTokenDto: RefreshTokenDto) {
    const { refreshToken } = refreshTokenDto;

    // 验证参数
    if (!refreshToken) {
      throw new ParameterException('刷新令牌不能为空', 'refreshToken');
    }

    try {
      // 验证刷新令牌
      const payload =
        await this.jwtAuthService.verifyRefreshToken(refreshToken);

      // 查找用户
      const user = await this.userService.findById(payload.userId);
      if (!user) {
        throw new BusinessException('用户不存在', 'USER_NOT_FOUND');
      }

      // 生成新的令牌对
      const tokens = this.jwtAuthService.generateTokenPair({
        id: user.id,
        username: user.username,
      });

      return {
        user: this.sanitizeUser(user),
        tokens,
      };
    } catch (error) {
      // 如果是JWT过期错误，使用401 UnauthorizedException
      if (
        error.name === 'TokenExpiredError' ||
        error.name === 'JsonWebTokenError'
      ) {
        throw new UnauthorizedException('刷新令牌无效或已过期');
      }
      // 其他错误使用400异常
      throw new BusinessException('令牌验证失败', 'TOKEN_VERIFICATION_ERROR');
    }
  }

  /**
   * 验证用户令牌
   */
  async validateUser(payload: JwtPayload): Promise<any> {
    const user = await this.userService.findById(payload.userId);
    if (!user) {
      throw new UnauthorizedException('用户不存在');
    }
    return this.sanitizeUser(user);
  }

  /**
   * 获取验证码
   */
  getCaptcha() {
    return CaptchaUtil.generateCaptcha();
  }

  /**
   * 用户登出
   */
  async logout(): Promise<void> {
    // 在实际应用中，这里可以将令牌加入黑名单
    // 目前简单返回成功
    return;
  }

  /**
   * 清理用户敏感信息
   */
  private sanitizeUser(user: any) {
    const { passwordHash, ...sanitizedUser } = user;
    return sanitizedUser;
  }
}
